package com.sdhs.common.utils;

import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import com.sdhs.common.core.domain.model.HrLeaveDataUtil;
import com.sdhs.common.core.domain.model.ProjectHolidayDTO;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.lang.management.ManagementFactory;
import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * 时间工具类
 * 
 * @author engineering
 */
@Component
public class DateUtils extends org.apache.commons.lang3.time.DateUtils
{

    @Autowired
    public JdbcTemplate jdbcTemplate;
    private static JdbcTemplate staticJdbcTemplate;
    @PostConstruct
    public void init(){
        staticJdbcTemplate=jdbcTemplate;
    }
    public static String YYYY = "yyyy";

    public static String YYYY_MM = "yyyy-MM";

    public static String YYYY_MM_DD = "yyyy-MM-dd";

    public static String YYYYMMDDHHMMSS = "yyyyMMddHHmmss";

    public static String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";

    private static String[] parsePatterns = {
            "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM", 
            "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM",
            "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"};

    /**
     * 获取当前Date型日期
     * 
     * @return Date() 当前日期
     */
    public static Date getNowDate()
    {
        return new Date();
    }

    public static String getDateMonth()
    {
        return dateTimeNow(YYYY_MM);
    }

    /**
     * 获取当前日期, 默认格式为yyyy-MM-dd
     * 
     * @return String
     */
    public static String getDate()
    {
        return dateTimeNow(YYYY_MM_DD);
    }

    public static final String getTime()
    {
        return dateTimeNow(YYYY_MM_DD_HH_MM_SS);
    }

    public static final String dateTimeNow()
    {
        return dateTimeNow(YYYYMMDDHHMMSS);
    }

    public static final String dateTimeNow(final String format)
    {
        return parseDateToStr(format, new Date());
    }

    public static final String dateTime(final Date date)
    {
        return parseDateToStr(YYYY_MM_DD, date);
    }

    public static final String parseDateToStr(final String format, final Date date)
    {
        return new SimpleDateFormat(format).format(date);
    }

    public static final Date dateTime(final String format, final String ts)
    {
        try
        {
            return new SimpleDateFormat(format).parse(ts);
        }
        catch (ParseException e)
        {
            throw new RuntimeException(e);
        }
    }

    /**
     * 日期路径 即年/月/日 如2018/08/08
     */
    public static final String datePath()
    {
        Date now = new Date();
        return DateFormatUtils.format(now, "yyyy/MM/dd");
    }

    /**
     * 日期路径 即年/月/日 如20180808
     */
    public static final String dateTime()
    {
        Date now = new Date();
        return DateFormatUtils.format(now, "yyyyMMdd");
    }

    /**
     * 日期型字符串转化为日期 格式
     */
    public static Date parseDate(Object str)
    {
        if (str == null)
        {
            return null;
        }
        try
        {
            return parseDate(str.toString(), parsePatterns);
        }
        catch (ParseException e)
        {
            return null;
        }
    }

    /**
     * 获取服务器启动时间
     */
    public static Date getServerStartDate()
    {
        long time = ManagementFactory.getRuntimeMXBean().getStartTime();
        return new Date(time);
    }

    /**
     * 计算相差天数
     */
    public static int differentDaysByMillisecond(Date date1, Date date2)
    {
        return Math.abs((int) ((date2.getTime() - date1.getTime()) / (1000 * 3600 * 24)));
    }

    /**
     * 计算时间差
     *
     * @param endDate 最后时间
     * @param startTime 开始时间
     * @return 时间差（天/小时/分钟）
     */
    public static String timeDistance(Date endDate, Date startTime)
    {
        long nd = 1000 * 24 * 60 * 60;
        long nh = 1000 * 60 * 60;
        long nm = 1000 * 60;
        // long ns = 1000;
        // 获得两个时间的毫秒时间差异
        long diff = endDate.getTime() - startTime.getTime();
        // 计算差多少天
        long day = diff / nd;
        // 计算差多少小时
        long hour = diff % nd / nh;
        // 计算差多少分钟
        long min = diff % nd % nh / nm;
        // 计算差多少秒//输出结果
        // long sec = diff % nd % nh % nm / ns;
        return day + "天" + hour + "小时" + min + "分钟";
    }

    /**
     * 得到两个日期间隔多少天
     * @param endDate
     * @param startTime
     * @return
     */
    public static String dayDistance(Date endDate, Date startTime){
        long nd = 1000 * 24 * 60 * 60;
        long nh = 1000 * 60 * 60;
        long nm = 1000 * 60;
        // long ns = 1000;
        // 获得两个时间的毫秒时间差异
        long diff = endDate.getTime() - startTime.getTime();
        // 计算差多少天
        long day = diff / nd;
        return day+"";
    }

    /**
     * 增加 LocalDateTime ==> Date
     */
    public static Date toDate(LocalDateTime temporalAccessor)
    {
        ZonedDateTime zdt = temporalAccessor.atZone(ZoneId.systemDefault());
        return Date.from(zdt.toInstant());
    }

    /**
     * 增加 LocalDate ==> Date
     */
    public static Date toDate(LocalDate temporalAccessor)
    {
        LocalDateTime localDateTime = LocalDateTime.of(temporalAccessor, LocalTime.of(0, 0, 0));
        ZonedDateTime zdt = localDateTime.atZone(ZoneId.systemDefault());
        return Date.from(zdt.toInstant());
    }

    /**
     * 得到当前周的第一天最后一天
     * @return
     */
    public static Map<String,String> getThisWeek(){
        Map<String,String> map = new HashMap<>();
        SimpleDateFormat format  = new SimpleDateFormat("YYYY-MM-dd HH:mm:ss");
        map.put("start",format.format(getBeginDayOfWeek()));
        map.put("end",format.format(getEndDayOfWeek()));
        return map;
    }

    /**
     * 得到一周开始时间
     * @return
     */
    public static Date getBeginDayOfWeek() {
        Date date = new Date();
        if (date == null) {
            return null;
        }
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        int dayofweek = cal.get(Calendar.DAY_OF_WEEK);
        if (dayofweek == 1) {
            dayofweek += 7;
        }
        cal.add(Calendar.DATE, 2 - dayofweek);
        return getDayStartTime(cal.getTime());
    }

    /**
     * 得到一周结束时间
     * @return
     */
    public static Date getEndDayOfWeek() {
        Calendar cal = Calendar.getInstance();
        cal.setTime(getBeginDayOfWeek());
        cal.add(Calendar.DAY_OF_WEEK, 6);
        Date weekEndSta = cal.getTime();
        return getDayEndTime(weekEndSta);
    }


    // 获取某个日期的开始时间
    public static Timestamp getDayStartTime(Date d) {
        Calendar calendar = Calendar.getInstance();
        if (null != d)
            calendar.setTime(d);
        calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH),
                calendar.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return new Timestamp(calendar.getTimeInMillis());
    }

    // 获取某个日期的结束时间
    public static Timestamp getDayEndTime(Date d) {
        Calendar calendar = Calendar.getInstance();
        if (null != d)
            calendar.setTime(d);
        calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH),
                calendar.get(Calendar.DAY_OF_MONTH), 23, 59, 59);
        calendar.set(Calendar.MILLISECOND, 999);
        return new Timestamp(calendar.getTimeInMillis());
    }

    /**
     * 取上周起始时间
     * @return
     */
    public static Map<String,String> getLastWeek(){
        Map<String,String> map = new HashMap<>();
        // 获取当前时间
        LocalDate currentDate = LocalDate.now();

        // 获取当前日期所在的星期几
        DayOfWeek currentDayOfWeek = currentDate.getDayOfWeek();
        // 计算需要减去的天数
        int daysToSubtract = currentDayOfWeek.getValue() - DayOfWeek.MONDAY.getValue();
        // 获取本周一的日期
        LocalDate thisMonday = currentDate.minusDays(daysToSubtract);
        // 获取上周一的日期
        LocalDate lastMonday = thisMonday.minusDays(7);

        // 计算需要增加的天数
        int daysToAdd = DayOfWeek.SUNDAY.getValue() - currentDayOfWeek.getValue();
        // 获取本周日的日期
        LocalDate thisSunday = currentDate.plusDays(daysToAdd);
        // 获取上周日的日期
        LocalDate lastSunday = thisSunday.minusDays(7);

        map.put("start",lastMonday.toString()+" 00:00:00");
        map.put("end",lastSunday.toString()+" 23:59:59");
        return map;
    }

    /**
     * 取当前月起始时间
     * @return
     */
    public static Map<String,String> getThisMonth(){
        Map<String,String> map = new HashMap<>();
        SimpleDateFormat format=new SimpleDateFormat("yyyy-MM-dd");
        Calendar c = Calendar.getInstance();
        c.set(Calendar.DAY_OF_MONTH,1);//设置为1号,当前日期既为本月第一天
        String monthStart = format.format(c.getTime())+" 00:00:00";
        Calendar ca = Calendar.getInstance();
        ca.set(Calendar.DAY_OF_MONTH, ca.getActualMaximum(Calendar.DAY_OF_MONTH));
        String monthEnd = format.format(ca.getTime())+" 23:59:59";
        map.put("start",monthStart);
        map.put("end",monthEnd);
        return map;
    }

    /**
     * 获取上月的数据
     * @return
     */
    public static Map<String,String> getLastMonth(){
        Map<String,String> map = new HashMap<>();
        // 获取当前时间
        LocalDate currentDate = LocalDate.now();
        // 获取上月一号的时间
        LocalDate firstDayOfLastMonth = currentDate.with(TemporalAdjusters.firstDayOfMonth()).minusMonths(1);
        // 获取为本月一号的时间
        LocalDate firstDayOfCurrentMonth = currentDate.with(TemporalAdjusters.firstDayOfMonth());
        // 上个月的最后一天的时间
        LocalDate last = firstDayOfCurrentMonth.minusDays(1);
        // 获取上个月的总天数
        int dayOfMonth = last.getDayOfMonth();

        map.put("start",firstDayOfLastMonth+" 00:00:00");
        map.put("end",last+" 23:59:59");
        return map;

    }

    /**
     * 取当前年起始时间
     * @return
     */
    public static Map<String,String> getThisYear(){
        Map<String,String> map = new HashMap<>();
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        Calendar c = Calendar.getInstance();
        c.set(c.get(Calendar.YEAR) ,0, 1);//开始时间日期
        String yearStart = format.format(c.getTime())+" 00:00:00";
        Calendar ca = Calendar.getInstance();
        ca.set(ca.get(Calendar.YEAR) ,11, ca.getActualMaximum(Calendar.DAY_OF_MONTH));//结束日期
        String yearEnd = format.format(ca.getTime())+" 23:59:59";
        map.put("start",yearStart);
        map.put("end",yearEnd);
        return map;
    }

    /**
     * 获取两个日期字符串之间的日期集合
     * @param startTime:String
     * @param endTime:String
     * @return list:yyyy-MM-dd
     */
    public static List<String> getBetweenDate(String startTime, String endTime){
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        // 声明保存日期集合
        List<String> list = new ArrayList<String>();
        try {
            // 转化成日期类型
            Date startDate = sdf.parse(startTime);
            Date endDate = sdf.parse(endTime);
            //用Calendar 进行日期比较判断
            Calendar calendar = Calendar.getInstance();
            while (startDate.getTime()<=endDate.getTime()){
                // 把日期添加到集合
                list.add(sdf.format(startDate));
                // 设置日期
                calendar.setTime(startDate);
                //把日期增加一天
                calendar.add(Calendar.DATE, 1);
                // 获取增加后的日期
                startDate=calendar.getTime();
            }
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return list;
    }

    /**
     * 获取两个日期之间所有的月份集合
     * @param startTime
     * @param endTime
     * @return：YYYY-MM
     */
    public static List<String> getMonthBetweenDate(String startTime, String endTime){
        SimpleDateFormat sdf = new SimpleDateFormat(YYYY_MM);
        // 声明保存日期集合
        List<String> list = new ArrayList<String>();
        try {
            // 转化成日期类型
            Date startDate = sdf.parse(startTime);
            Date endDate = sdf.parse(endTime);

            //用Calendar 进行日期比较判断
            Calendar calendar = Calendar.getInstance();
            while (startDate.getTime()<=endDate.getTime()){
                // 把日期添加到集合
                list.add(sdf.format(startDate));
                // 设置日期
                calendar.setTime(startDate);
                //把日期增加一天
                calendar.add(Calendar.MONTH, 1);
                // 获取增加后的日期
                startDate=calendar.getTime();
            }
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return list;
    }

    /**
     * 计算两个日期间的工作时长
     *
     * @param begintime yyyy-MM-dd HH:mm:ss
     * @param endTime   yyyy-MM-dd HH:mm:ss
     * @return 工作时长/毫秒
     */
    public static long calTime(String begintime, String endTime) {
        Date startDate = DateUtil.parse(begintime);//节点到达时间
        Date endDate = DateUtil.parse(endTime);//当前时间
        int compareNum = DateUtil.compare(startDate, endDate);
        if (compareNum > 0) {
            String temp = endTime;
            endTime = begintime;
            begintime = temp;
        }
        startDate = DateUtil.parse(begintime);//节点到达时间
        endDate = DateUtil.parse(endTime);//当前时间

        long millis = DateUtil.between(startDate, endDate, DateUnit.MS);
        //开始日期当天
        String beginDateStr = DateUtil.format(DateUtil.parse(begintime), "yyyy-MM-dd");
        String beginTimeStr = DateUtil.format(DateUtil.parse(begintime), "HH:mm:ss");
        //截止日期当天
        String endDateStr = DateUtil.format(DateUtil.parse(endTime), "yyyy-MM-dd");
        String endTimeStr = DateUtil.format(DateUtil.parse(endTime), "HH:mm:ss");
        long subMills = 0;//需要减去的时长
        Map<String, Map<String, String>> workDayInfoMap = initWorkdayInfo();
        // 同一天
        if (beginDateStr.equals(endDateStr)) {
            if (isWorkingDay(beginDateStr)) {
                //工作日
                long tempMills = calWorkDayRestMills(workDayInfoMap, beginDateStr, beginTimeStr, endTimeStr);
                subMills += tempMills;
            } else {
                subMills = millis;//同一天且非工作日
            }
        } else {
            long daysLen = DateUtil.between(DateUtil.parse(beginDateStr), DateUtil.parse(endDateStr), DateUnit.DAY, false);//相差天数
            //处理开始日期
            if (isWorkingDay(beginDateStr)) {
                long tempMills = calWorkDayRestMills(workDayInfoMap, beginDateStr, beginTimeStr, "23:59:59") + 1000;
                subMills += tempMills;
            } else {
                long tempMills = DateUtil.between(DateUtil.parse(begintime), DateUtil.parse(beginDateStr + " 23:59:59"), DateUnit.MS) + 1000;
                subMills += tempMills;
            }
            //处理中间日期
            if (daysLen > 1) {
                for (int i = 1; i < daysLen; i++) {
                    String tempDateStr = DateUtil.format(DateUtil.offsetDay(DateUtil.parse(begintime), i), "yyyy-MM-dd");
                    if (isWorkingDay(tempDateStr)) {
                        long tempMills = calWorkDayRestMills(workDayInfoMap, tempDateStr, "00:00:00", "23:59:59") + 1000;
                        subMills += tempMills;
                    } else {
                        long tempMills = DateUtil.between(DateUtil.parse(tempDateStr + " 00:00:00")
                                , DateUtil.parse(tempDateStr + " 23:59:59"), DateUnit.MS) + 1000;
                        subMills += tempMills;
                    }
                }
            }
            //处理截止日期
            if (isWorkingDay(endDateStr)) {
                long tempMills = calWorkDayRestMills(workDayInfoMap, endDateStr, "00:00:00", endTimeStr);//工时长
                subMills += tempMills;
            } else {
                long tempMills = DateUtil.between(DateUtil.parse(endDateStr + " 00:00:00"), DateUtil.parse(endTime), DateUnit.MS);
                subMills += tempMills;
            }
        }
        millis = millis - subMills;
        return millis;
    }

    /**
     * 计算两个请假日期的起止时间、是否全天、是否节假日
     *
     * @param begintime yyyy-MM-dd HH:mm:ss
     * @param endTime   yyyy-MM-dd HH:mm:ss
     * @return 工作时长/毫秒
     */
    public static List<HrLeaveDataUtil> calHrLeaveTime(String begintime, String endTime) {
        Date startDate = DateUtil.parse(begintime);//节点到达时间
        Date endDate = DateUtil.parse(endTime);//当前时间
        int compareNum = DateUtil.compare(startDate, endDate);
        if (compareNum > 0) {
            String temp = endTime;
            endTime = begintime;
            begintime = temp;
        }
        startDate = DateUtil.parse(begintime);//节点到达时间
        endDate = DateUtil.parse(endTime);//当前时间

        //开始日期当天
        String beginDateStr = DateUtil.format(DateUtil.parse(begintime), "yyyy-MM-dd");
        String beginTimeStr = DateUtil.format(DateUtil.parse(begintime), "HH:mm:ss");
        //截止日期当天
        String endDateStr = DateUtil.format(DateUtil.parse(endTime), "yyyy-MM-dd");
        String endTimeStr = DateUtil.format(DateUtil.parse(endTime), "HH:mm:ss");
        long subMills = 0;//需要减去的时长
        Map<String, Map<String, String>> workDayInfoMap = initWorkdayInfo();
        List<HrLeaveDataUtil> mapList=new ArrayList<>();
        if (beginDateStr.equals(endDateStr)) {
            // 同一天
            HrLeaveDataUtil hrLeaveData=new HrLeaveDataUtil();
            hrLeaveData.setStartTime(beginDateStr+" "+beginTimeStr);
            hrLeaveData.setEndTime(endDateStr+" "+endTimeStr);
            hrLeaveData.setLeaveDate(beginDateStr);
            if (!isHoliday(beginDateStr)) {
                //是工作日
                //是否是全天
                String isFull = calWorkDayIsFull(workDayInfoMap, beginDateStr, beginTimeStr, endTimeStr);

                hrLeaveData.setIsFullDay(isFull);
                hrLeaveData.setIsWorkDay("0");

                mapList.add(hrLeaveData);
            } else {
                //同一天且非工作日
                hrLeaveData.setIsFullDay("1");
                hrLeaveData.setIsWorkDay("1");
                mapList.add(hrLeaveData);
            }
        } else {
            //不是同一天
            long daysLen = DateUtil.between(DateUtil.parse(beginDateStr), DateUtil.parse(endDateStr), DateUnit.DAY, false);//相差天数
            //处理开始日期
            if (!isHoliday(beginDateStr)) {
                //工作日
                //是否是全天
                HrLeaveDataUtil hrLeaveData=new HrLeaveDataUtil();
                hrLeaveData.setLeaveDate(beginDateStr);
                hrLeaveData.setStartTime(beginDateStr+" "+beginTimeStr);
                hrLeaveData.setEndTime(beginDateStr+" "+"23:59:59");
                String isFull = calWorkDayIsFull(workDayInfoMap, beginDateStr, beginTimeStr, "23:59:59");
                hrLeaveData.setIsFullDay(isFull);
                hrLeaveData.setIsWorkDay("0");
                mapList.add(hrLeaveData);
            } else {
                //非工作日

                HrLeaveDataUtil hrLeaveData=new HrLeaveDataUtil();
                hrLeaveData.setStartTime(beginDateStr+" "+beginTimeStr);
                hrLeaveData.setEndTime(beginDateStr+" "+"23:59:59");
                hrLeaveData.setLeaveDate(beginDateStr);
                hrLeaveData.setIsFullDay("1");
                hrLeaveData.setIsWorkDay("1");
                mapList.add(hrLeaveData);
            }
            //处理中间日期
            if (daysLen > 1) {
                for (int i = 1; i < daysLen; i++) {
                    String tempDateStr = DateUtil.format(DateUtil.offsetDay(DateUtil.parse(begintime), i), "yyyy-MM-dd");
                    HrLeaveDataUtil hrLeaveData=new HrLeaveDataUtil();
                    hrLeaveData.setLeaveDate(tempDateStr);
                    hrLeaveData.setStartTime(tempDateStr+" "+"00:00:00");
                    hrLeaveData.setEndTime(tempDateStr+" "+"23:59:59");
                    hrLeaveData.setIsFullDay("0");
                    if (!isHoliday(tempDateStr)) {
                        hrLeaveData.setIsWorkDay("0");
                    } else {
                        hrLeaveData.setIsWorkDay("1");
                    }
                    mapList.add(hrLeaveData);
                }
            }
            HrLeaveDataUtil hrLeaveData=new HrLeaveDataUtil();
            hrLeaveData.setStartTime(endDateStr+" "+"00:00:00");
            hrLeaveData.setEndTime(endDateStr+" "+endTimeStr);
            hrLeaveData.setLeaveDate(endDateStr);
            //处理截止日期
            if (!isHoliday(endDateStr)) {

                String isFull = calWorkDayIsFull(workDayInfoMap, endDateStr, "00:00:00", endTimeStr);
                hrLeaveData.setIsFullDay(isFull);
                hrLeaveData.setIsWorkDay("0");
            } else {
                hrLeaveData.setIsFullDay("1");
                hrLeaveData.setIsWorkDay("1");
            }
            mapList.add(hrLeaveData);
        }
        return mapList;
    }
    /**
     * 计算工作日，开始时间--截止时间知之间的非工作日时间长【日期是同一天，且是工作日】
     *
     * @param workDayInfoMap 工作日工作时间信息
     * @param dateStr        yyyy-MM-dd
     * @param beginTimeStr   HH:mm:ss
     * @param endTimeStr     HH:mm:ss
     * @return
     */
    private static Long calWorkDayRestMills(Map<String, Map<String, String>> workDayInfoMap, String dateStr, String beginTimeStr, String endTimeStr) {
        if (workDayInfoMap == null || workDayInfoMap.size() == 0
                || dateStr == null || beginTimeStr == null || endTimeStr == null) {
            return null;
        }
        //step1:判断时间大小
        Integer hourB = DateUtil.hour(DateUtil.parse(beginTimeStr), true);
        Integer hourE = DateUtil.hour(DateUtil.parse(endTimeStr), true);
        if (hourB > hourE) {
            String temp = endTimeStr;
            endTimeStr = beginTimeStr;
            beginTimeStr = temp;
        }
        //step2:获取两个时间的时间差，单位毫秒
        long allMills = DateUtil.between(DateUtil.parse(dateStr + " " + beginTimeStr)
                , DateUtil.parse(dateStr + " " + endTimeStr), DateUnit.MS);
        //上午工作时长
        long workMills1 = 0;
        //下午工作时长
        long workMills2 = 0;
        //step3：获取月份及工作日信息
        Integer month = 1 + DateUtil.month(DateUtil.parse(dateStr));//DateUtil.month从0开始算
        String monthStr = String.valueOf(month);
        if (month < 10) {
            monthStr = "0" + month;
        }
        Map<String, String> workInfo = workDayInfoMap.get(monthStr);
        if (workInfo == null) {
            return null;
        }
        String amBegin = workInfo.get("amBegin");
        String amEnd = workInfo.get("amEnd");
        String pmBegin = workInfo.get("pmBegin");
        String pmEnd = workInfo.get("pmEnd");
        //step4:开始时间、结束时间和工作日时间对比
        int bcr1 = DateUtil.compare(DateUtil.parse(beginTimeStr), DateUtil.parse(amBegin));//1表示前面大，0相等，-1表示前面小
        int bcr2 = DateUtil.compare(DateUtil.parse(beginTimeStr), DateUtil.parse(amEnd));
        int bcr3 = DateUtil.compare(DateUtil.parse(beginTimeStr), DateUtil.parse(pmBegin));
        int bcr4 = DateUtil.compare(DateUtil.parse(beginTimeStr), DateUtil.parse(pmEnd));

        int ecr1 = DateUtil.compare(DateUtil.parse(endTimeStr), DateUtil.parse(amBegin));
        int ecr2 = DateUtil.compare(DateUtil.parse(endTimeStr), DateUtil.parse(amEnd));
        int ecr3 = DateUtil.compare(DateUtil.parse(endTimeStr), DateUtil.parse(pmBegin));
        int ecr4 = DateUtil.compare(DateUtil.parse(endTimeStr), DateUtil.parse(pmEnd));
        //step4：获取工作时长
        if (bcr1 < 0) {//上午上班前
            if (ecr1 < 0) {//上午上班前--无需处理
            } else if (ecr1 >= 0 && ecr2 < 0) {//上午上班区间
                workMills1 = DateUtil.between(DateUtil.parse(dateStr + " " + amBegin)
                        , DateUtil.parse(dateStr + " " + endTimeStr), DateUnit.MS);
            } else if (ecr2 >= 0 && ecr3 < 0) {//中午休息区间
                workMills1 = DateUtil.between(DateUtil.parse(dateStr + " " + amBegin)
                        , DateUtil.parse(dateStr + " " + amEnd), DateUnit.MS);
            } else if (ecr3 >= 0 && ecr4 < 0) {//下午上班区间
                workMills1 = DateUtil.between(DateUtil.parse(dateStr + " " + amBegin)
                        , DateUtil.parse(dateStr + " " + amEnd), DateUnit.MS);
                workMills2 = DateUtil.between(DateUtil.parse(dateStr + " " + pmBegin)
                        , DateUtil.parse(dateStr + " " + endTimeStr), DateUnit.MS);
            } else if (ecr4 >= 0) {//下午下班时间
                workMills1 = DateUtil.between(DateUtil.parse(dateStr + " " + amBegin)
                        , DateUtil.parse(dateStr + " " + amEnd), DateUnit.MS);
                workMills2 = DateUtil.between(DateUtil.parse(dateStr + " " + pmBegin)
                        , DateUtil.parse(dateStr + " " + pmEnd), DateUnit.MS);
            }
        } else if (bcr1 >= 0 && bcr2 < 0) {//上午上班区间
            if (ecr1 >= 0 && ecr2 < 0) {//上午上班区间
                workMills1 = DateUtil.between(DateUtil.parse(dateStr + " " + beginTimeStr)
                        , DateUtil.parse(dateStr + " " + endTimeStr), DateUnit.MS);
            } else if (ecr2 >= 0 && ecr3 < 0) {//中午休息区间
                workMills1 = DateUtil.between(DateUtil.parse(dateStr + " " + beginTimeStr)
                        , DateUtil.parse(dateStr + " " + amEnd), DateUnit.MS);
            } else if (ecr3 >= 0 && ecr4 < 0) {//下午上班区间
                workMills1 = DateUtil.between(DateUtil.parse(dateStr + " " + beginTimeStr)
                        , DateUtil.parse(dateStr + " " + amEnd), DateUnit.MS);
                workMills2 = DateUtil.between(DateUtil.parse(dateStr + " " + pmBegin)
                        , DateUtil.parse(dateStr + " " + endTimeStr), DateUnit.MS);
            } else if (ecr4 >= 0) {//下午下班时间
                workMills1 = DateUtil.between(DateUtil.parse(dateStr + " " + beginTimeStr)
                        , DateUtil.parse(dateStr + " " + amEnd), DateUnit.MS);
                workMills2 = DateUtil.between(DateUtil.parse(dateStr + " " + pmBegin)
                        , DateUtil.parse(dateStr + " " + pmEnd), DateUnit.MS);
            }
        } else if (bcr2 >= 0 && bcr3 < 0) {//中午休息区间
            if (ecr2 >= 0 && ecr3 < 0) {//中午休息区间--无需处理
            } else if (ecr3 >= 0 && ecr4 < 0) {//下午上班区间
                workMills2 = DateUtil.between(DateUtil.parse(dateStr + " " + pmBegin)
                        , DateUtil.parse(dateStr + " " + endTimeStr), DateUnit.MS);
            } else if (ecr4 >= 0) {//下午下班时间
                workMills2 = DateUtil.between(DateUtil.parse(dateStr + " " + pmBegin)
                        , DateUtil.parse(dateStr + " " + pmEnd), DateUnit.MS);
            }
        } else if (bcr3 >= 0 && bcr4 < 0) {//下午上班区间
            if (ecr3 >= 0 && ecr4 < 0) {//下午上班区间
                workMills2 = DateUtil.between(DateUtil.parse(dateStr + " " + beginTimeStr)
                        , DateUtil.parse(dateStr + " " + endTimeStr), DateUnit.MS);
            } else if (ecr4 >= 0) {//下午下班时间
                workMills2 = DateUtil.between(DateUtil.parse(dateStr + " " + beginTimeStr)
                        , DateUtil.parse(dateStr + " " + pmEnd), DateUnit.MS);
            }
        } else if (bcr4 >= 0) {//下午下班时间--无需处理
        }
        //不是工作时段的时长（毫秒）
        long noWorkMills = allMills - workMills1 - workMills2;
        return noWorkMills;
    }


    /**
     * 计算工作日，是否是整天【日期是同一天，且是工作日】
     *
     * @param workDayInfoMap 工作日工作时间信息
     * @param dateStr        yyyy-MM-dd
     * @param beginTimeStr   HH:mm:ss(请假开始时间)
     * @param endTimeStr     HH:mm:ss(请假结束时间)
     * @return
     */
    private static String calWorkDayIsFull(Map<String, Map<String, String>> workDayInfoMap, String dateStr, String beginTimeStr, String endTimeStr) {
        if (workDayInfoMap == null || workDayInfoMap.size() == 0
                || dateStr == null || beginTimeStr == null || endTimeStr == null) {
            return null;
        }
        //step1:判断时间大小
        Integer hourB = DateUtil.hour(DateUtil.parse(beginTimeStr), true);
        Integer hourE = DateUtil.hour(DateUtil.parse(endTimeStr), true);
        if (hourB > hourE) {
            String temp = endTimeStr;
            endTimeStr = beginTimeStr;
            beginTimeStr = temp;
        }


        String amBegin = "08:30:00";
        String pmEnd = "17:00:00";


        //step4:开始时间、结束时间和工作日时间对比
        //请假开始时间和上班开始时间比较
        int bcr11 = DateUtil.compare(DateUtil.parse(beginTimeStr), DateUtil.parse(amBegin));//1表示前面大，0相等，-1表示前面小
        //比较请假请假结束时间和上班结束时间
        int ecr41 = DateUtil.compare(DateUtil.parse(endTimeStr), DateUtil.parse(pmEnd));

        //是否请了全天  0是 1否
        String fullDay="0";
        if((bcr11==0||bcr11==-1)&&(ecr41==1||ecr41==0)){
            //请假开始时间等于或小于上班结束时间    并且   请假结束时间大于或等于上班结束时间
            fullDay="0";
        }else{
            fullDay="1";
        }



        return fullDay;
    }


    /**
     * 判断是否为工作日
     *
     * @param dateStr yyyy-MM-dd
     * @return
     */
    public static Boolean isWorkingDay(String dateStr) {


        //hutool工具jar,5.3.0版本【1是工作日，2-7表示周一到周六】
        int week = DateUtil.dayOfWeek(DateUtil.parse(dateStr));
        if (week == 1 || week == 7) {
            return false;//周末
        }
        return true;
    }


    public static  boolean isHoliday(String date) {
        //加入缓存
        List<String> holidayDates=new ArrayList<>();
        holidayDates=(List<String>) CacheManager.get("holidayDate");
        if(TextUtil.isNull(holidayDates)) {
            holidayDates=new ArrayList<>();
            String sql = "select holiday_date as holidayDate from project_holiday where is_holiday='0'";
            List<ProjectHolidayDTO> list = staticJdbcTemplate.query(sql, new BeanPropertyRowMapper<ProjectHolidayDTO>(ProjectHolidayDTO.class));

            if (TextUtil.isNotNull(list)) {
                for (ProjectHolidayDTO projectHolidayDTO : list) {
                    String holidayDate1 = projectHolidayDTO.getHolidayDate();
                    holidayDates.add(holidayDate1);
                }
            }
            if (TextUtil.isNotNull(holidayDates)) {
                CacheManager.put("holidayDate",holidayDates,30, TimeUnit.DAYS);
            }
        }

        //判断是否是节假日
        boolean contains = holidayDates.contains(date);
        return contains;
    }

    /**
     * 初始化工作日工作时间【生产环境中请使用配置表】
     *
     * @return
     */
    public static Map<String, Map<String, String>> initWorkdayInfo() {
        Map<String, Map<String, String>> workDayInfoMap = new HashMap<>();
        //冬令时
        Map<String, String> map = new HashMap<>();
        map.put("amBegin", "08:30:00");
        map.put("amEnd", "11:30:00");
        map.put("pmBegin", "13:30:00");
        map.put("pmEnd", "17:00:00");
        workDayInfoMap.put("10", map);
        workDayInfoMap.put("11", map);
        workDayInfoMap.put("12", map);
        workDayInfoMap.put("01", map);
        workDayInfoMap.put("02", map);
        workDayInfoMap.put("03", map);
        workDayInfoMap.put("04", map);
        //
        workDayInfoMap.put("05", map);
        workDayInfoMap.put("06", map);
        workDayInfoMap.put("07", map);
        workDayInfoMap.put("08", map);
        workDayInfoMap.put("09", map);
        //夏令时
//        map = new HashMap<>();
//        map.put("amBegin", "08:30:00");
//        map.put("amEnd", "11:30:00");
//        map.put("pmBegin", "13:30:00");
//        map.put("pmEnd", "18:00:00");
//        workDayInfoMap.put("05", map);
//        workDayInfoMap.put("06", map);
//        workDayInfoMap.put("07", map);
//        workDayInfoMap.put("08", map);
//        workDayInfoMap.put("09", map);
        return workDayInfoMap;
    }



}
